﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;
using iTextSharp.text.html.simpleparser;
using Common.Views;

namespace DataAccess
{
    public class ProductRepository : ConnectionClass
    {
        public ProductRepository()
            : base()
        {

        }

        public void UpdateProduct(Product p)
        {
            Product OP = GetProductByID(p.ID);
            db.Products.Attach(OP);
            db.Products.ApplyCurrentValues(p);
            db.SaveChanges();
        }

        public Product GetProductByID(int id)
        {
            return db.Products.SingleOrDefault(p => p.ID == id);
        }

        public IEnumerable<Product> GetAllProducts()
        {
            return db.Products;
        }

        public IEnumerable<Product> SearhProduct(int category, string name, int LeastPrice, int MaxPrice)
        {
            List<Product> foundProducts = new List<Product>();
            foreach (Product p in db.Products)
            {
                if (p.Price > LeastPrice && p.Price < MaxPrice)
                {
                    if ((p.Name == name || name == "") && (p.CategoryID == category || category == 0))
                        foundProducts.Add(p);
                }

                if(LeastPrice == 0 && MaxPrice == 0)
                {
                    if ((p.Name == name || name == "") && (p.CategoryID == category || category == 0))
                        foundProducts.Add(p);
                }
            }

            return foundProducts.AsEnumerable();
        }

        public IEnumerable<Category> GetAllCategories()
        {
            return db.Categories;
        }

        public void AddRating(UserProductRating u)
        {
            db.AddToUserProductRatings(u);
            db.SaveChanges();
        }

        public IEnumerable<UserProductRating> getAllRatings()
        {
            return db.UserProductRatings;
        }

        public void addComment(Comment c)
        {
            db.AddToComments(c);
            db.SaveChanges();
        }

        public List<Comment> getComments(int productID)
        {
            return db.Comments.Where(c => c.ProductID == productID).ToList();
        }

        public IEnumerable<Common.Views.UserItem> GetUserProducts(string username)
        {
          
           return (from OD in db.OrderDetails
                    join O in db.Orders on OD.OrderID equals O.ID
                    join p in db.Products on OD.ProductID equals p.ID
                    join upf in db.UserProductFaults on p.ID equals upf.ProductID
                    where O.UserName == username
                    select new Common.Views.UserItem
                    {
                        ID = p.ID,
                        PurchaseID = O.ID,
                        ProductName = p.Name,
                        Quantity = OD.Quantity,
                        DatePurchased = O.Date,
                        WarranyExpires = O.Date.AddYears(2),
                        AmountPurchased = (double)p.Price,
                        Features = p.Features,
                        FaultID = (int)upf.FaultID,
                        Faults = upf.Fault.Description

                    });
        }


        public IEnumerable<Common.Views.UserItem> GetUserProductsForFaults(string username)
        {
            return (from OD in db.OrderDetails
                    join O in db.Orders on OD.OrderID equals O.ID
                    join p in db.Products on OD.ProductID equals p.ID
                    join upf in db.UserProductFaults on p.ID equals upf.ProductID
                    where O.UserName == username
                    select new Common.Views.UserItem
                    {
                        ID = p.ID,
                        ProductName = p.Name,
                        DatePurchased = O.Date,
                        WarranyExpires = O.Date

                    });
        }


        public Common.Views.UserItem GetUserProductsDetails(string username, int id)
        {
            return (from OD in db.OrderDetails
                    join O in db.Orders on OD.OrderID equals O.ID
                    join p in db.Products on OD.ProductID equals p.ID
                    join upf in db.UserProductFaults on p.ID equals upf.ProductID
                    where O.UserName == username && p.ID == id
                    select new Common.Views.UserItem
                    {
                        ID = p.ID,
                        ProductName = p.Name,
                        Quantity = OD.Quantity,
                        DatePurchased = O.Date,
                        WarranyExpires = O.Date.AddYears(2),
                        AmountPurchased = (double)p.Price,
                        Features = p.Features,
                        Faults = upf.Fault.Description

                    }).SingleOrDefault();
        }

        public IEnumerable<Product> GetAllUserProducts(string username)
        {
            return (from O in db.Orders
                    join OD in db.OrderDetails on O.ID equals OD.OrderID
                    join p in db.Products on OD.ProductID equals p.ID
                    where O.UserName == username
                    select p);
        }

        public Common.Views.ProductDetails GetProductDetailsByID(int id, string username)
        {
            return (from O in db.Orders
                    join OD in db.OrderDetails on O.ID equals OD.OrderID
                    join p in db.Products on OD.ProductID equals p.ID
                    where O.UserName == username && p.ID == id
                    select new Common.Views.ProductDetails()
                    {
                        ID = p.ID,
                        Name = p.Name,
                        Price = (double)p.Price,
                        DatePurchased = O.Date,
                        WarrantyExpires = O.Date.AddYears(2)

                    }).SingleOrDefault();
        }

        public string PDFOrder(Guid orderId)
        {
            string contents = "";
            Order order = new OrderReposity().GetOrderByID(orderId);
            Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
            PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("C:\\Users\\Andrea Consiglio\\Desktop\\" + order.ID + ".pdf", FileMode.Create));
            doc.Open();
            User user = new UserRepository().GetUserByUserName(order.UserName);
            contents = "<b>Online Boutique</b><br/><br/>";
            contents += "<table><tr><td><b>Order Id:</b>" + order.ID + "</td></tr><tr><td><b>To:</b>" + user.FirstName + " " + user.LastName + "</td></tr><tr><td><b>Address:</b>" + user.HouseNo + ", " + user.StreetName + ", " + user.TownName + ", " + user.Country.CountryName + "</td></tr><tr><td><b>Date:</b>" + order.Date.ToShortDateString() + "</td></table>";
            contents += "<br/>";
            contents += "<table><b><tr><td>Code</td><td>Name</td><td></td><td>Unit Price</td><td>Qty</td><td>Total</td></tr></b>";

            List<OrderDetail> allDetailsInOrder = new OrderReposity().GetOrderDetailByOrderID(order.ID).ToList();
            double subTotal = 0;
            foreach (OrderDetail od in allDetailsInOrder)
            {
                double totalForItem = 0;

                totalForItem = (double)od.Product.Price * od.Quantity;
                totalForItem = Math.Round(totalForItem, 2);
                contents += "<tr><td>" + od.ProductID + "</td><td>" + od.Product.Name + "</td><td>" + od.Quantity + "</td><td>€" + totalForItem + "</td></tr>";

                subTotal += totalForItem;
            }

            contents += "</table><br/>";

            contents += "<table><tr><td></td><td></td><td><b>Sub-Total:</b></td><td>€" + subTotal + "</td><td></td></tr>";
            contents += "</table>";

            //Read string contents using stream reader and convert html to parsed conent
            var parsedHtmlElements = HTMLWorker.ParseToList(new StringReader(contents), null);

            //Get each array values from parsed elements and add to the PDF document
            foreach (var htmlElement in parsedHtmlElements)
                doc.Add(htmlElement as IElement);

            doc.Close();

            string location = "C:\\Users\\Andrea Consiglio\\Desktop\\" + order.ID + ".pdf";

            return location;
        }

        public void ProduceReport(List<ProductReport> list, string opt)
        {
            string contents = "";
            string path = "";
            string name = DateTime.Now.ToLongDateString();
            name = name.Replace('/', '-');
            string guid = Guid.NewGuid().ToString();
            Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);


            if (opt.Equals("Most Purchased"))
            {
                path = "Purchased";
                PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("C:\\Users\\Andrea Consiglio\\Desktop\\" + name + " - " + guid + ".pdf", FileMode.Create));
                doc.Open();
                contents += "<h2>Most Purchased Items</h2><br/>";
                contents += "<table>";
                contents += "<tr><b><td>Rank</td><td>Id</td><td>Name</td><td>No Of Purchases</td></b></tr>";
                int counter = 0;
                foreach (ProductReport p in list)
                {
                    counter++;
                    contents += "<tr><td>" + counter + "</td><td>" + p.ProductID + "</td><td>" + p.ProductName + "</td><td>" + p.NoOfTimesBought + "</td></tr>";
                }
                contents += "</table>";


            }
            else if (opt.Equals("Highly Rated"))
            {
                path = "Rated";
                PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("C:\\Users\\Owner\\Desktop\\Reports\\Rated\\" + name + " - " + guid + ".pdf", FileMode.Create));
                doc.Open();
                contents += "<h2>Most Rated Items</h2><br/>";
                contents += "<table>";
                contents += "<tr><b><td>Rank</td><td>Id</td><td>Name</td><td>Rating</td><td>No of Times Rated</td></b></tr>";
                int counter = 0;
                foreach (ProductReport p in list)
                {
                    counter++;
                    contents += "<tr><td>" + counter + "</td><td>" + p.ProductID + "</td><td>" + p.ProductName + "</td><td>" + p.ProductRating + "</td><td>" + p.NoOfTimesBought + "</td></tr>";
                }
                contents += "</table>";
            }
            else if (opt.Equals("Highest faults"))
            {
                path = "HighestFaults";
                PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("C:\\Users\\Owner\\Desktop\\Reports\\HighestFaults\\" + name + " - " + guid + ".pdf", FileMode.Create));
                doc.Open();
                contents += "<h2>Products with Highest Number of Faults</h2><br/>";
                contents += "<table>";
                contents += "<tr><b><td>Rank</td><td>Id</td><td>Name</td><td>No Of faults</td></b></tr>";
                int counter = 0;
                foreach (ProductReport p in list)
                {
                    counter++;
                    contents += "<tr><td>" + counter + "</td><td>" + p.ProductID + "</td><td>" + p.ProductName + "</td><td>" + p.NoOfFaultsReported + "</td></tr>";
                }
                contents += "</table>";
            }
            else
            {
                //least faults
                path = "LeastFaults";
                PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("C:\\Users\\Owner\\Desktop\\Reports\\LeastFaults\\" + name + " - " + guid + ".pdf", FileMode.Create));
                doc.Open();
                contents += "<h2>Products With least number of Faults</h2><br/>";
                contents += "<table>";
                contents += "<tr><b><td>Rank</td><td>Id</td><td>Name</td><td>No Of faults</td></b></tr>";
                int counter = 0;
                foreach (ProductReport p in list)
                {
                    counter++;
                    contents += "<tr><td>" + counter + "</td><td>" + p.ProductID + "</td><td>" + p.ProductName + "</td><td>" + p.NoOfFaultsReported + "</td></tr>";
                }
                contents += "</table>";
            }
            var parsedHtmlElements = HTMLWorker.ParseToList(new StringReader(contents), null);
            foreach (var htmlElement in parsedHtmlElements)
                doc.Add(htmlElement as IElement);

            doc.Close();

            System.Diagnostics.Process.Start(@"C:\\Users\\Andrea Consiglio\\Desktop\\" + path + "\\" + name + " - " + guid + ".pdf");
        }
    }
}
